#include "frontend.h"
#include <sstream>

namespace gcode {

	FrontEnd::FrontEnd(ErrorReporter &er, ProgramOverride &po, CommandDatabase &cmddb, std::istream *is /* = 0*/)
	: is_(is), er_(er), po_(po), bt_(cmddb), parser_(er), scanner_(er),
	reportEmptyBlocks_(false), reportSkippedBlocks_(false)
	{
		scanner_.setInputStream(is_);
		parser_.setScanner(&scanner_);
		parser_.setProgramOverride(&po_);
	}

	void FrontEnd::setInputStream(std::istream *is)
	{
		scanner_.setInputStream(is);
	}

	void FrontEnd::translate()
	{
		ProgramComponentID programComponent;
		Block block;
		CommandList cmdlist;
		char s[256];
		std::ostringstream ostr(s, 256);

		scanner_.resetInputStream();
		parser_.reset();
		er_.reset();
		do {
			programComponent = parser_.getProgramComponent();
			switch (programComponent) {
			case PROGRAM_START:
				er_.report(ERRORCLS_COMMENT, ERRORMSG_PROGRAM_START);
				break;
			case PROGRAM_LEADER:
				ostr << parser_.getLeader() << std::ends;
				er_.report(ERRORCLS_COMMENT, ERRORMSG_NEUTRAL, s);
				ostr.seekp(0, std::ios::beg);
				break;
			case PROGRAM_NUMBER:
				ostr << parser_.getProgramNumber() << std::ends;
				er_.report(ERRORCLS_COMMENT, ERRORMSG_PROGRAM_NUMBER, s);
				ostr.seekp(0, std::ios::beg);
				break;
			case PROGRAM_BLOCK:
				block = parser_.getBlock();
				switch (block.getID()) {
				case BLOCK_NONE:
					//if (last line did not contain an M30)
					//	er_.report(ERRORCLS_COMMENT, ERRORMSG_PROGRAM_END_UNEXPECTED);
					break;
				case BLOCK_EMPTY:
					if (reportEmptyBlocks_)
						er_.report(ERRORCLS_COMMENT, ERRORMSG_BLOCK_EMPTY);
					break;
				case BLOCK_SKIPPED:
					if (reportSkippedBlocks_)
						er_.report(ERRORCLS_COMMENT, ERRORMSG_BLOCK_SKIPPED,
							"", scanner_.getRow() - 1, 1);
					break;
				case BLOCK_STANDARD:
					cmdlist = bt_.getCommandList(block);
					break;
				}
				break;
			case PROGRAM_END:
				//if (last line did contain an M30)
					er_.report(ERRORCLS_COMMENT, ERRORMSG_PROGRAM_END);
				break;
			case PROGRAM_ERROR:
				er_.report(ERRORCLS_COMMENT, ERRORMSG_TOO_MANY_ERRORS);
				break;
			}
		} while (programComponent != PROGRAM_END && programComponent != PROGRAM_ERROR);
	}

} // namespace gcode
